﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Xml.Linq;

namespace OrderManager.Orders.Paipai
{
    class PaipaiOrderManager : OrderManagerBase
    {
        private const string PAIPAI_POP = "http://api.paipai.com/";
        private const string PAIPAI_POP_MODIFYSELLERCOMMENT = "deal/modifySellerNote.xhtml";
        private const string PAIPAI_POP_DETAIL = "/deal/sellerSearchDealList.xhtml";
        private const string PAIPAI_POP_MODIFYADDRESS = "user/modifyReceiverAddress.xhtml";
        private const string PAIPAI_POP_GETBUYERADDRESS = "user/getReceiverAddressList.xhtml";
        private const string PAIPAI_POP_CLOSEORDER = "deal/sellerCancelDeal.xhtml";

        private const String FORMAT_DEFAULT = FORMAT_XML;
        private const String FORMAT_XML = "xml";
        private const String FORMAT_JSON = "json";

        private const String CHARSET = "utf-8";
        private const string SIGN = "sign";
        // 请求方法
        private String method = "post";

        public string UIN { get; private set; }

        public string AccessToken { get; private set; }

        public string AppOAuthID { get; private set; }

        public string AppOAuthKey { get; private set; }

        public override string Type
        {
            get { return OrderManagerBase.ShopType_WangGou; }
        }

        public override void Initialize(System.Xml.Linq.XElement xelement)
        {
            this.UIN = xelement.Elements("UIN").First().Value;
            this.AccessToken = xelement.Elements("AccessToken").First().Value;
            this.AppOAuthID = xelement.Elements("AppOAuthID").First().Value;
            this.AppOAuthKey = xelement.Elements("AppOAuthKey").First().Value;

            if (string.IsNullOrWhiteSpace(this.UIN))
            {
                throw new Exception("UIN is empty");
            }

            if (string.IsNullOrWhiteSpace(this.AccessToken))
            {
                throw new Exception("AccessToken is empty");
            }

            if (string.IsNullOrWhiteSpace(this.AppOAuthID))
            {
                throw new Exception("AppOAuthID is empty");
            }
        }

        private string GetTime()
        {
            Int64 retval = 0;
            DateTime st = new DateTime(1970, 1, 1);
            TimeSpan t = (DateTime.Now.ToUniversalTime() - st);
            retval = (Int64)(t.TotalMilliseconds + 0.5);
            return retval.ToString();
        }

        private int GetRandomValue()
        {
            Random radom = new Random();
            return radom.Next(1, int.MaxValue);
        }

        private string ComputeSignCode(string method, string apiURI, Dictionary<string, string> parameters, string appOAuthKey, string encoding)
        {
            try
            {
                //添加地址
                string requestHeader = method.ToUpper() + "&" + Http.HttpUtil.UrlEncode(apiURI, Encoding.GetEncoding(encoding));

                //处理参数
                var items = parameters.OrderBy(key => key.Key).Where(item => string.IsNullOrWhiteSpace(item.Key) == false && string.IsNullOrWhiteSpace(item.Value) == false);
                string requestPara = string.Join("&", items.Select(item => item.Key + "=" + item.Value));
                string encoded = Http.HttpUtil.UrlEncode(requestPara, Encoding.GetEncoding(encoding));

                //计算签名
                Byte[] signatureKey = Encoding.Default.GetBytes(this.AppOAuthKey + "&");
                HMACSHA1 hmacsha1 = new HMACSHA1(signatureKey);
                hmacsha1.ComputeHash(Encoding.GetEncoding(encoding).GetBytes(requestHeader + "&" + encoded));
                byte[] hash = hmacsha1.Hash;
                string signature = Convert.ToBase64String(hash);
                return signature;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private string InvokeOpenApi(string serviceUrl, Dictionary<string, string> parameters)
        {
            if (parameters.ContainsKey("timeStamp") == false)
            {
                parameters.Add("timeStamp", GetTime());
            }

            if (parameters.ContainsKey("randomValue") == false)
            {
                parameters.Add("randomValue", GetRandomValue().ToString());
            }

            parameters["uin"] = this.UIN;
            parameters["accessToken"] = this.AccessToken;
            parameters["appOAuthID"] = this.AppOAuthID;
            parameters["format"] = FORMAT_XML;
            parameters["charset"] = CHARSET;
            string sin = ComputeSignCode(method, serviceUrl, parameters, this.AppOAuthKey, CHARSET);
            parameters["sign"] = sin;
            return Http.HttpUtil.DoPost(PAIPAI_POP + serviceUrl, parameters);
        }

        private bool DownloadPage(int page, ref int totalPage, OrderDownloadArgs args)
        {
            int totalCount = 0;
            Dictionary<string, string> para = new Dictionary<string, string>();
            para["sellerUin"] = this.UIN;
            //para["dealNoteType"] = "UN_LABEL";
            para["dealState"] = "STATE_COD_WAIT_SHIP";
            para["listItem"] = "1";
            para["pageIndex"] = page.ToString();
            para["timeType"] = "CREATE";
            para["timeBegin"] = args.StartTime.ToString("yyyy-MM-dd HH:mm:00");
            para["timeEnd"] = args.EndTime.ToString("yyyy-MM-dd HH:mm:00");
            string content = InvokeOpenApi(PAIPAI_POP_DETAIL, para);
            XDocument xDoc = XDocument.Parse(content);

            if (xDoc.Root.Element("errorCode").Value.Trim() != "0")
            {
                throw new Exception(xDoc.Root.Element("errorMessage").Value);
            }

            if (xDoc.Root.Element("pageIndex").Value.Trim() != page.ToString())
            {
                throw new Exception("要下载的页，与返回的页数据不匹配");
            }

            totalPage = int.Parse(xDoc.Root.Element("pageTotal").Value.Trim());
            totalCount = int.Parse(xDoc.Root.Element("countTotal").Value.Trim());
            int count = 0;
            foreach (XElement xe in xDoc.Root.Elements("dealList").First().Elements("dealInfo"))
            {
                Order order = new Order();
                order.ShopInfo = this.Type + " " + this.ShopName;
                order.ID = xe.Element("dealCode").Value;
                order.Name = xe.Element("buyerUin").Value;
                order.NickName = xe.Element("receiverAddress").Value;
                order.RealName = xe.Element("receiverName").Value;
                order.Money = (float.Parse(xe.Element("dealPayFeeTotal").Value) / 100).ToString("F2");
                order.Address = xe.Element("receiverAddress").Value;
                order.Phone = xe.Element("receiverMobile").Value;
                if (string.IsNullOrWhiteSpace(order.Phone))
                {
                    order.Phone = xe.Element("receiverPhone").Value;
                }
                order.BuyerComment = xe.Element("buyerRemark").Value;
                order.SellerComment = xe.Element("dealNote").Value;
                order.Flag = (OrderFlag)(Enum.Parse(typeof(OrderFlag), xe.Element("dealNoteType").Value));
                order.CreateTime = DateTime.Parse(xe.Element("createTime").Value);
                foreach (XElement item in xe.Element("itemListNew").Elements("itemInfo"))
                {
                    OrderItem orderItem = new OrderItem();
                    orderItem.Name = item.Element("stockLocalCode").Value;
                    string[] pro = item.Element("stockAttr").Value.Split('|');
                    orderItem.Color = pro[0].Split(':')[1];
                    orderItem.Size = pro[1].Split(':')[1];
                    orderItem.Money = (float.Parse(item.Element("itemDealPrice").Value) - float.Parse(item.Element("itemAdjustPrice").Value)) / 100;
                    orderItem.Count = int.Parse(item.Element("itemDealCount").Value);
                    order.AllItems.Add(orderItem);
                }
                order.FirstItem = order.AllItems[0];
                count++;
                this.OnOrderDownloading(new OrderDownloadEventArgs(totalCount, (page - 1) * 10 + count, order));
            }

            return totalPage > page;
        }

        private void DownloadOrders(string platform, OrderDownloadArgs args)
        {
            int totalPage = 0;
            int page = 1;

            while (this.DownloadPage(page++, ref totalPage, args)) ;
        }

        protected override void DownloadOrders(OrderDownloadArgs args)
        {
            args.StartTime = DateTime.Now.AddDays(-1);
            args.EndTime = DateTime.Now;
            this.DownloadOrders("ds", args);
        }

        //protected override void DownloadOrders(OrderDownloadArgs args)
        //{
        //    for (int i = 0; i < 10 & this.isStop == false; i++)
        //    {
        //        Order order = new Order(this.Type + " " + this.ShopName, "821234536", "何大天", "何沣道", "123", "无地址", "10086", new OrderItem { Name = "单鞋", Color = "红色", Size = "38", Money = 136 });

        //        if (i % 2 == 0)
        //        {
        //            order.AllItems.Add(new OrderItem { Name = "凉鞋", Color = "黑色", Money = 123, Size = "36" });
        //            order.AllItems.Add(new OrderItem { Name = "凉鞋", Color = "黑色", Money = 123, Size = "36" });
        //        }
        //        this.OnOrderDownloading(new OrderDownloadEventArgs(10, i + 1, order));
        //        Thread.Sleep(100);
        //    }
        //}

        public override Order[] GetOrdersByName(string id)
        {
            throw new NotImplementedException();
        }

        public override Order[] GetOrdersByPhone(string phone)
        {
            throw new NotImplementedException();
        }

        public override Order[] GetOrdersByNameAndAddress(string name, string address)
        {
            throw new NotImplementedException();
        }

        public override void Update(string orderID, OrderFlag flag, string address, string sellerComment)
        {
            throw new NotImplementedException();
        }
    }
}
